home *** CD-ROM | disk | FTP | other *** search
- /*
- * ispell.c - An interactive spelling corrector.
- *
- * Copyright (c), 1983, by Pace Willisson
- * Permission for non-profit use is hereby granted.
- * All other rights reserved.
- *
- * 1987, Robert McQueer, added:
- * -w option & handling of extra legal word characters
- * -d option for alternate dictionary file
- * -p option & WORDLIST variable for alternate personal dictionary
- * -x option to suppress .bak files.
- * 8 bit text & config.h parameters
- * 1987, Geoff Kuenning, added:
- * -c option for creating suffix suggestions from raw words
- * suffixes in personal dictionary file
- * hashed personal dictionary file
- * -S option for unsorted word lists
- * 1987, Greg Schaffer, added:
- * -T option (for TeX and LaTeX instead of troff) [later changed to -t]
- * passes over \ till next whitespace.
- * does not recognize % (comment)
- * 1989, Tomas Rokicki, added:
- * ispell'local'words to indicate rest of line for local words
- * -L option to write local words when done
- * fixed `sleep' so some error messages could be seen.
- * 1989, Loren J. Rittle, added:
- * Fixed ISpell to use proper STDOUT/STDIN streams when used in
- * non-interactive modes.
- * ARexx Server Mode, invoke with -r option ( for rexx )
- * Thanks to Tomas Rokicki for MinRexx! and example code.
- * 1990, Loren J. Rittle, reworked:
- * Converted to SAS/C v5.10.
- * Added full prototype checking.
- * Fixed more bugs, many memory related.
- * Finally left UNIX behind completely.
- * Got rid of alot of (what I would call) kludge code, left
- * over from the original port job. See amiga.c for more details.
- * 1991, Loren J. Rittle, added:
- * many new ARexx Server Mode commands.
- * released to the world.
- * 1992, W.G.J. Langeveld, added:
- * -R switch, same as -r, but prints out line numbers and column numbers
- * during "filecheck".
- * 1992, Loren J. Rittle, reworked:
- * Converted to SAS/C v6.0.
- * Reworked W.G.J. Langeveld's '-R' switch to make new ARexx interface
- * point instead of startup time option. Once again, '-r' is the only
- * server mode provided by ispell.
- */
-
- #undef _STRICT_ANSI
- #include <stdio.h>
- #define _STRICT_ANSI
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- extern int creat (char *, int);
- #pragma msg 148 ignore push
- #pragma msg 149 ignore push
- #pragma msg 61 ignore push
- #include <dos/dos.h>
- #pragma msg 149 pop
- #pragma msg 61 pop
- #include "config.h"
- #include "ispell.h"
- #include "version.h"
-
- struct rexxCommandList rcl[] =
- {
- {"add", &rexxadd},
- {"quickadd", &rexxquickadd},
- {"check", &rexxcheck},
- {"quickcheck", &rexxquickcheck},
- {"lookup", &rexxlookup},
- {"filecheck", &rexxfilecheck},
- {"extendedfilecheck", &rexxextendedfilecheck},
- {"version", &rexxversion},
- {"exit", &rexxexit},
- {NULL, NULL}
- };
-
- SHORT KeepGoing = TRUE; /* main loop control value */
-
- char rootword[BUFSIZ];
- struct dent *lastdent;
-
- char *hashstrings;
- struct hashheader hashheader;
-
- char tempfile[200];
-
- #define ISTEXTERM(c) (((c) == '{') || \
- ((c) == '}') || \
- ((c) == '[') || \
- ((c) == ']'))
-
- int li, co; /* lines, columns */
-
- FILE *infile;
- FILE *outfile;
-
- char hashname[MAXPATHLEN];
-
- /*
- ** we use extended character set range specifically to allow intl.
- ** character set characters. We are being REALLY paranoid about indexing
- ** this array - explicitly cast into unsigned INTEGER, then mask
- ** If NO8BIT is set, text will be masked to ascii range.
- */
- static int Trynum;
- #ifdef NO8BIT
- static char Try[128];
- static char Checkch[128];
- #define iswordch(X) (Checkch[((unsigned)(X))&0x7f])
- #else
- static char Try[256];
- static char Checkch[256];
- #define iswordch(X) (Checkch[((unsigned)(X))&0xff])
- #endif
-
- static int sortit = 1;
-
- void givehelp (void)
- {
- erase ();
- printcon (Version_ID);
- printcon ("\n");
- printcon ("Whenever a word is found that is not in the dictionary,\n");
- printcon ("it is printed on the first line of the screen. If the dictionary\n");
- printcon ("contains any similar words, they are listed with a single digit\n");
- printcon ("next to each one. You have the option of replacing the word\n");
- printcon ("completely, or choosing one of the suggested words.\n");
- printcon ("\n");
- printcon ("Commands are:\n\n");
- printcon ("R Replace the misspelled word completely.\n");
- printcon ("Space Accept the word this time only\n");
- printcon ("A Accept the word for the rest of this file.\n");
- printcon ("I Accept the word, and put it in your private dictionary.\n");
- printcon ("0-9 Replace with one of the suggested words.\n");
- printcon ("L Look up words via regular expression.\n");
- printcon ("Q Write the rest of this file, ignoring misspellings, ");
- printcon ("and start next file.\n");
- printcon ("X Exit immediately. Asks for confirmation. ");
- printcon ("Leaves file unchanged.\n");
- printcon ("^L Redraw screen.\n");
- printcon ("\n\n");
- printcon ("-- Type space to continue --");
- while (getccon () != ' ')
- ;
- }
-
- int cflag = 0;
- int lflag = 0;
- int incfileflag = 0;
- int aflag = 0;
- int fflag = 0;
- int sflag = 0;
- int xflag = 0;
- int tflag = 0;
- int llflag = 0;
- int rflag = 0;
- /*
- * Willy's flag: for more extended spell-file capability
- */
- int wflag = 0;
-
- #define MAXPOSSIBLE 100 /* Max no. of possibilities to generate */
-
- char possibilities[MAXPOSSIBLE][BUFSIZ];
- int pcount;
- int maxposslen;
-
- char *askfilename;
-
- static char *Cmd;
-
- void usage (void)
- {
- fprintf (stderr,
- "Usage: %s [-dfile | -pfile | -wchars | -t | -x | -S] file .....\n",
- Cmd);
- fprintf (stderr,
- " %s -r\n",
- Cmd);
- fprintf (stderr,
- " %s [-dfile | -pfile | -wchars] -l\n",
- Cmd);
- fprintf (stderr,
- " %s [-dfile | -pfile | -ffile | -s] {-a | -A}\n",
- Cmd);
- fprintf (stderr, " %s [-wchars] -c\n", Cmd);
- fprintf (stderr, " %s -v\n", Cmd);
- exit (1);
- }
-
- static void initckch (void)
- {
- register int c;
-
- Trynum = 0;
- #ifdef NO8BIT
- for (c = 0; c < 128; ++c)
- {
- #else
- for (c = 0; c < 256; ++c)
- {
- #endif
- if (myalpha ((char) c))
- {
- Checkch[c] = (char) 1;
- if (myupper ((char) c))
- {
- Try[Trynum] = (char) c;
- ++Trynum;
- }
- }
- else
- Checkch[c] = (char) 0;
- }
- }
-
- void main (int argc, char **argv)
- {
- char *p;
- char *cpd;
- char num[4];
- unsigned mask;
- static char outbuf[BUFSIZ];
-
- Cmd = *argv;
-
- initckch ();
- sprintf (hashname, "%s%s", LIBDIR, DEFHASH);
-
- cpd = NULL;
-
- argv++;
- argc--;
- while (argc && **argv == '-')
- {
- switch ((*argv)[1])
- {
- case 'r':
- rflag++;
- lflag++;
- break;
- case 'v':
- printf ("%s\n", Version_ID);
- exit (0);
- case 't':
- tflag++;
- break;
- case 'A':
- incfileflag = 1;
- aflag = 1;
- break;
- case 'a':
- aflag++;
- break;
- case 'c':
- cflag++;
- lflag++;
- break;
- case 'x':
- xflag++;
- break;
- case 'f':
- fflag++;
- p = (*argv) + 2;
- if (*p == '\0')
- {
- argv++;
- argc--;
- if (argc == 0)
- usage ();
- p = *argv;
- }
- askfilename = p;
- break;
- case 'l':
- lflag++;
- break;
- case 'L':
- llflag++;
- break;
- case 's':
- sflag++;
- break;
- case 'S':
- sortit = 0;
- break;
- case 'p':
- cpd = (*argv) + 2;
- if (*cpd == '\0')
- {
- argv++;
- argc--;
- if (argc == 0)
- usage ();
- cpd = *argv;
- }
- break;
- case 'd':
- p = (*argv) + 2;
- if (*p == '\0')
- {
- argv++;
- argc--;
- if (argc == 0)
- usage ();
- p = *argv;
- }
- if (*p == '/')
- strcpy (hashname, p);
- else
- sprintf (hashname, "%s%s", LIBDIR, p);
- break;
- case 'w':
- num[3] = '\0';
- #ifdef NO8BIT
- mask = 0x7f;
- #else
- mask = 0xff;
- #endif
- p = (*argv) + 2;
- if (*p == '\0')
- {
- argv++;
- argc--;
- if (argc == 0)
- usage ();
- p = *argv;
- }
- while (Trynum <= mask && *p != '\0')
- {
- if (*p != 'n' && *p != '\\')
- {
- Checkch[((unsigned) (*p)) & mask] = (char) 1;
- Try[Trynum] = *p & mask;
- ++p;
- }
- else
- {
- ++p;
- num[0] = '\0';
- num[1] = '\0';
- num[2] = '\0';
- num[3] = '\0';
- if (isdigit (p[0]))
- num[0] = p[0];
- if (isdigit (p[1]))
- num[1] = p[1];
- if (isdigit (p[2]))
- num[2] = p[2];
- if (p[-1] == 'n')
- {
- p += strlen (num);
- num[0] = atoi (num);
- }
- else
- {
- p += strlen (num);
- if (num[0])
- num[0] -= '0';
- if (num[1])
- {
- num[0] <<= 3;
- num[0] += num[1] - '0';
- }
- if (num[2])
- {
- num[0] <<= 3;
- num[0] += num[2] - '0';
- }
- }
- Try[Trynum] = num[0] & mask;
- Checkch[num[0] & mask] = 1;
- }
- ++Trynum;
- }
- break;
- default:
- usage ();
- }
- argv++;
- argc--;
- }
-
- if (!argc && !lflag && !aflag && !rflag)
- usage ();
-
- if (linit () < 0)
- exit (0);
-
- treeinit (cpd);
-
- if (rflag)
- {
- servermode ();
- exit (0);
- }
-
- if (aflag)
- {
- askmode ();
- exit (0);
- }
-
- setbuf (stdout, outbuf);
- if (lflag)
- {
- infile = stdin;
- checkfile ();
- exit (0);
- }
-
- terminit ();
-
- while (argc--)
- dofile (*argv++);
-
- done ();
- }
-
- char firstbuf[BUFSIZ], secondbuf[BUFSIZ];
- char *currentchar;
- char token[BUFSIZ];
-
- int quit;
-
- char *currentfile = NULL;
-
- void dofile (char *filename)
- {
- int c;
- char bakfile[256];
- char *cp;
-
- currentfile = filename;
-
- if ((infile = fopen (filename, "r")) == NULL)
- {
- fprintf (stderr, "Can't open %s\n", filename);
- sleep (2);
- return;
- }
-
- if (access (filename, 2) < 0)
- {
- fprintf (stderr, "Can't write to %s\n", filename);
- sleep (2);
- return;
- }
-
- tmpnam (tempfile);
- if ((outfile = fopen (tempfile, "w")) == NULL)
- {
- fprintf (stderr, "Can't create %s\n", tempfile);
- sleep (2);
- return;
- }
-
- quit = 0;
-
- /* See if the file is a .tex file. If so, set the appropriate flag. */
- if ((cp = strrchr (filename, '.')) != NULL && strcmp (cp, ".tex") == 0)
- tflag = 1;
- checkfile ();
-
- fclose (infile);
- fclose (outfile);
-
- if (!cflag)
- treeoutput ();
-
- if ((infile = fopen (tempfile, "r")) == NULL)
- {
- fprintf (stderr, "temporary file disappeared (%s)\n", tempfile);
- sleep (2);
- return;
- }
-
- sprintf (bakfile, "%s%s", filename, BAKEXT);
- remove (bakfile);
- if (rename (filename, bakfile))
- {
- fprintf (stderr, "can't rename %s to %s\n", filename, bakfile);
- sleep (2);
- return;
- }
-
- /* if we can't write new, preserve .bak regardless of xflag */
- if ((outfile = fopen (filename, "w")) == NULL)
- {
- fprintf (stderr, "can't create %s\n", filename);
- sleep (2);
- return;
- }
-
- while ((c = getc (infile)) != EOF)
- putc (c, outfile);
-
- fclose (infile);
- fclose (outfile);
-
- remove (tempfile);
- if (xflag)
- remove (bakfile);
- }
-
- struct RexxMsg *RexxMsg;
-
- void checkfile (void)
- {
- register char *p;
- register int len;
- int addflag;
- int count = 0;
-
- /*
- * Willy's mod: keep track of line number
- */
- long linenum = 0;
-
- secondbuf[0] = 0;
-
- while (1)
- {
- strcpy (firstbuf, secondbuf);
- if (quit)
- { /* quit can't be set in l mode */
- while (fgets (secondbuf, sizeof secondbuf, infile) != NULL)
- fputs (secondbuf, outfile);
- break;
- }
-
- if (fgets (secondbuf, sizeof secondbuf, infile) == NULL)
- break;
- /*
- * Willy's mod: keep track of line number
- */
- linenum++;
-
- currentchar = secondbuf;
- addflag = 0;
- len = strlen (secondbuf) - 1;
-
- if (!tflag)
- {
- /* skip over .if */
- if (strncmp (currentchar, ".if t", 5) == 0
- || strncmp (currentchar, ".if n", 5) == 0)
- {
- copyout (¤tchar, 5);
- while (*currentchar && isspace (*currentchar))
- copyout (¤tchar, 1);
- }
-
- /* skip over .ds XX or .nr XX */
- if (strncmp (currentchar, ".ds ", 4) == 0
- || strncmp (currentchar, ".de ", 4) == 0
- || strncmp (currentchar, ".nr ", 4) == 0)
- {
- copyout (¤tchar, 3);
- while (*currentchar && isspace (*currentchar))
- copyout (¤tchar, 1);
- while (*currentchar && !isspace (*currentchar))
- copyout (¤tchar, 1);
- if (*currentchar == 0)
- {
- if (!lflag)
- putc ('\n', outfile);
- continue;
- }
- }
- }
-
- if (secondbuf[len] == '\n')
- secondbuf[len] = 0;
-
- /* if this is a formatter command, skip over it */
- if (!tflag && *currentchar == '.')
- {
- while (*currentchar && !myspace (*currentchar))
- {
- if (!lflag)
- putc (*currentchar, outfile);
- currentchar++;
- }
- if (*currentchar == 0)
- {
- if (!lflag)
- putc ('\n', outfile);
- continue;
- }
- }
-
- while (1)
- {
- while (*currentchar && !iswordch (*currentchar))
- {
- if (tflag) /* TeX or LaTeX stuff */
- {
- if (*currentchar == '\\')
- {
- /* skip till whitespace */
- while (*currentchar &&
- (!isspace (*currentchar) &&
- !ISTEXTERM (*currentchar)))
- {
- if (!lflag)
- putc (*currentchar, outfile);
- currentchar++;
- }
- continue;
- }
- }
- else
- {
- /* formatting escape sequences */
- if (*currentchar == '\\')
- {
- switch (currentchar[1])
- {
- case 'f':
- if (currentchar[2] != '(')
- {
- /* font change: \fX */
- copyout (¤tchar, 3);
- }
- else
- {
- /* font change: \f(XY */
- copyout (¤tchar, 5);
- }
- continue;
- case 's':
- /* size change */
- p = currentchar + 2;
- if (*p == '+' || *p == '-')
- p++;
- /* This looks wierd 'cause we assume
- ** *p is now a digit.
- */
- if (isdigit (p[1]))
- p++;
- copyout (¤tchar,
- p - currentchar + 1);
- continue;
- case '(':
- /* extended char set escape: \(XX */
- copyout (¤tchar, 4);
- continue;
- case '*':
- if (currentchar[2] != '(')
- copyout (¤tchar, 3);
- else
- copyout (¤tchar, 5);
- continue;
- default:
- break;
- }
- }
- }
-
- if (!lflag)
- putc (*currentchar, outfile);
- currentchar++;
- }
-
- if (*currentchar == 0)
- break;
-
- p = token;
- while (iswordch (*currentchar) ||
- (*currentchar == '\'' &&
- iswordch (*(currentchar + 1))))
- *p++ = *currentchar++;
- *p = 0;
- /*
- * mods by tom rokicki to handle local document words automagically
- */
- if (token[0] == 'i' &&
- strcmp (token, "ispell'local'words") == 0)
- {
- addflag = 1;
- }
- else
- {
- if (addflag)
- {
- if (!good (token))
- {
- treeinsert (token, 0);
- }
- }
- if (lflag)
- {
- if (!good (token) && !cflag)
- if (rflag) {
- /*
- * Willy's mod: if wflag, print out word, line number and colum
- */
- if (wflag) {
- static char var[64];
- static char value[64];
-
- sprintf (value, "%d", ++count);
- SetRexxVar (RexxMsg, "ISPELLRESULT.COUNT", value, strlen (value));
-
- sprintf (var,"ISPELLRESULT.%d.WORD", count);
- SetRexxVar (RexxMsg, var, token, strlen (token));
-
- sprintf (value, "%d", linenum);
- sprintf (var,"ISPELLRESULT.%d.LINE", count);
- SetRexxVar (RexxMsg, var, value, strlen (value));
-
- sprintf (value, "%d", currentchar - secondbuf - strlen(token) + 1);
- sprintf (var,"ISPELLRESULT.%d.COLUMN", count);
- SetRexxVar (RexxMsg, var, value, strlen (value));
- }
- else {
- fprintf (outfile, "%s\n", token);
- }
- }
- else
- fprintf (stdout, "%s\n", token);
- }
- else
- {
- if (!quit)
- correct (token, ¤tchar);
- }
- }
- if (!lflag)
- fprintf (outfile, "%s", token);
- }
- if (!lflag)
- putc ('\n', outfile);
- }
- if (llflag)
- {
- lldump ();
- }
- }
-
- void correct (char *token, char **currentchar)
- {
- register int c;
- register int i;
- int col_ht;
- int ncols;
- char *start_l2;
- char *begintoken;
-
- begintoken = *currentchar - strlen (token);
-
- checkagain:
- if (good (token))
- return;
-
- erase ();
- printcon (" %s", token);
- if (currentfile)
- printcon (" File: %s", currentfile);
- printcon ("\n\n");
-
- makepossibilities (token);
-
- /*
- * Make sure we have enough room on the screen to hold the
- * possibilities. Reduce the list if necessary. co / (maxposslen + 8)
- * is the maximum number of columns that will fit.
- */
- col_ht = li - 6; /* Height of columns of words */
- ncols = co / (maxposslen + 8);
- if (pcount > ncols * col_ht)
- pcount = ncols * col_ht;
-
- #ifdef EQUAL_COLUMNS
- /*
- * Equalize the column sizes. The last column will be short.
- */
- col_ht = (pcount + ncols - 1) / ncols;
- #endif
-
- for (i = 0; i < pcount; i++)
- {
- move (2 + (i % col_ht), (maxposslen + 8) * (i / col_ht));
- printcon ("%2d: %s", i, possibilities[i]);
- }
-
- move (li - 3, 0);
- show_line (firstbuf, firstbuf, 0);
-
- start_l2 = secondbuf;
- if (line_size (secondbuf, *currentchar) > co - 1)
- {
- start_l2 = begintoken - (co / 2);
- while (start_l2 < begintoken)
- {
- i = line_size (start_l2, *currentchar) + 1;
- if (i <= co)
- break;
- start_l2 += i - co;
- }
- if (start_l2 > begintoken)
- start_l2 = begintoken;
- if (start_l2 < secondbuf)
- start_l2 = secondbuf;
- }
- show_line (start_l2, begintoken, strlen (token));
-
- while (1)
- {
- switch (c = (getccon () & NOPARITY))
- {
- case 'Z' & 037:
- stop ();
- erase ();
- goto checkagain;
- case ' ':
- erase ();
- return;
- case 'x':
- case 'X':
- printcon ("Are you sure you want to throw away your changes? ");
- c = (getccon () & NOPARITY);
- if (c == 'y' || c == 'Y')
- {
- erase ();
- done ();
- }
- putchar (7);
- goto checkagain;
- case 'i':
- case 'I':
- treeinsert (token, 1);
- erase ();
- return;
- case 'a':
- case 'A':
- treeinsert (token, 0);
- if (llflag)
- llinsert (token);
- erase ();
- return;
- case 'L' & 037:
- goto checkagain;
- case '?':
- givehelp ();
- goto checkagain;
- case 'r':
- case 'R':
- move (li - 1, 0);
- printcon ("Replace with: ");
- if (getline (token) == NULL)
- {
- putccon (7);
- erase ();
- goto checkagain;
- }
- inserttoken (secondbuf, begintoken, token, currentchar);
- erase ();
- goto checkagain;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- i = c - '0';
- if (pcount > 10
- && i > 0 && i <= (pcount - 1) / 10)
- {
- c = getccon () & NOPARITY;
- if (c >= '0' && c <= '9')
- i = i * 10 + c - '0';
- else if (c != '\n')
- {
- putccon (7);
- break;
- }
- }
- if (i < pcount)
- {
- strcpy (token, possibilities[i]);
- inserttoken (secondbuf, begintoken,
- token, currentchar);
- erase ();
- return;
- }
- putccon (7);
- break;
- case '\r': /* This makes typing \n after single digits */
- case '\n': /* ..less obnoxious */
- break;
- case 'l':
- case 'L':
- {
- char buf[100];
- move (li - 1, 0);
- printcon ("Lookup string ('*' is wildcard): ");
- if (getline (buf) == NULL)
- {
- putccon (7);
- erase ();
- goto checkagain;
- }
- printcon ("\n\n");
- lookharder (buf);
- erase ();
- goto checkagain;
- }
- case 'q':
- case 'Q':
- quit = 1;
- erase ();
- return;
- default:
- putccon (7);
- break;
- }
- }
- }
-
- void show_line (char *line, char *invstart, int invlen)
- {
- register int width;
-
- width = 0;
- while (line != invstart && width < co - 1)
- width += show_char (*line++, width);
- if (invlen)
- {
- inverse ();
- while (--invlen >= 0 && width < co - 1)
- width += show_char (*line++, width);
- normal ();
- }
- while (*line && width < co - 1)
- width += show_char (*line++, width);
- printcon ("\n");
- }
-
- int show_char (int ch, int linew)
- {
- if (ch == '\t')
- {
- putccon ('\t');
- return 8 - (linew & 0x07);
- }
- else if (ch < ' ')
- {
- putccon ('^');
- putccon (ch + 'A' - '\001');
- return 2;
- }
- putccon (ch);
- return 1;
- }
-
- int line_size (char *buf, char *bufend)
- {
- register int width;
-
- for (width = 0; buf < bufend && *buf; buf++)
- {
- if (*buf == '\t')
- width = (width + 8) & ~0x07;
- else if (*buf < ' ')
- width += 2;
- else
- width++;
- }
- return width;
- }
-
- void inserttoken (char *buf, char *start, char *token, char **currentchar)
- {
- char copy[BUFSIZ];
- register char *p, *q;
-
- strcpy (copy, buf);
-
- for (p = buf, q = copy; p != start; p++, q++)
- *p = *q;
- q += *currentchar - start;
- while (*token && iswordch (*token))
- *p++ = *token++;
- *currentchar = p;
- if (*token)
- {
-
- /*
- ** The token changed to two words. Split it up and save the
- ** second one for later.
- */
-
- *p++ = *token;
- *token++ = '\0';
- while (*token)
- *p++ = *token++;
- }
- while (*p++ = *q++)
- ;
- }
-
- int casecmp (char *a, char *b)
- {
- register char *ap;
- register char *bp;
-
- for (ap = a, bp = b; *ap; ap++, bp++)
- {
- if (mylower (*ap))
- {
- if (mylower (*bp))
- {
- if (*ap != *bp)
- return *ap - *bp;
- }
- else
- {
- if (toupper (*ap) != *bp)
- return toupper (*ap) - *bp;
- }
- }
- else
- {
- if (myupper (*bp))
- {
- if (*ap != *bp)
- return *ap - *bp;
- }
- else
- {
- if (tolower (*ap) != *bp)
- return tolower (*ap) - *bp;
- }
- }
- }
- if (*bp != '\0')
- return -((int)*bp);
- return strcmp (a, b);
- }
-
- void makepossibilities (char *word)
- {
- register int i;
-
- for (i = 0; i < MAXPOSSIBLE; i++)
- possibilities[i][0] = 0;
- pcount = 0;
- maxposslen = 0;
-
- #ifdef CAPITALIZE
- wrongcapital (word);
- #endif
- if (pcount < MAXPOSSIBLE)
- wrongletter (word);
- if (pcount < MAXPOSSIBLE)
- extraletter (word);
- if (pcount < MAXPOSSIBLE)
- missingletter (word);
- if (pcount < MAXPOSSIBLE)
- transposedletter (word);
-
- if (sortit && pcount)
- qsort ((char *) possibilities, pcount,
- sizeof (possibilities[0]), casecmp);
- }
-
- int insert (char *word)
- {
- register int i;
-
- for (i = 0; i < pcount; i++)
- if (strcmp (possibilities[i], word) == 0)
- return (0);
-
- strcpy (possibilities[pcount++], word);
- i = strlen (word);
- if (i > maxposslen)
- maxposslen = i;
- if (pcount >= MAXPOSSIBLE)
- return (-1);
- else
- return (0);
- }
-
- #ifdef CAPITALIZE
- int wrongcapital (char *word)
- {
- char newword[BUFSIZ];
-
- /*
- ** All-uppercase is always legal. If the word matches, "ins_cap"
- ** will recapitalize it correctly.
- */
- strcpy (newword, word);
- upcase (newword);
- if (good (newword))
- return ins_cap (newword, word);
- return 0;
- }
-
- #endif
-
- void wrongletter (char *word)
- {
- register int i, j, c, n;
- char newword[BUFSIZ];
-
- n = strlen (word);
- strcpy (newword, word);
- #ifdef CAPITALIZE
- upcase (newword);
- #endif
-
- for (i = 0; i < n; i++)
- {
- for (j = 0; j < Trynum; ++j)
- {
- newword[i] = Try[j];
- if (good (newword))
- {
- if (ins_cap (newword, word) < 0)
- return;
- }
- }
- #ifdef CAPITALIZE
- c = word[i];
- if (islower (c))
- newword[i] = toupper (c);
- else
- newword[i] = c;
- #else
- newword[i] = word[i];
- #endif
- }
- }
-
- void extraletter (char *word)
- {
- char newword[BUFSIZ];
- register char *p, *s, *t;
-
- if (strlen (word) < 3)
- return;
-
- for (p = word; *p; p++)
- {
- for (s = word, t = newword; *s; s++)
- if (s != p)
- *t++ = *s;
- *t = 0;
- #ifdef CAPITALIZE
- if (good (upcase (newword)))
- {
- if (ins_cap (newword, word) < 0)
- return;
- }
- #else
- if (good (newword))
- {
- if (ins_cap (newword, word) < 0)
- return;
- }
- #endif
- }
- }
-
- void missingletter (char *word)
- {
- char newword[BUFSIZ];
- register char *p, *r, *s, *t;
- register int i;
-
- for (p = word; p == word || p[-1]; p++)
- {
- for (s = newword, t = word; t != p; s++, t++)
- *s = *t;
- r = s++;
- while (*t)
- *s++ = *t++;
- *s = 0;
- for (i = 0; i < Trynum; ++i)
- {
- *r = Try[i];
- #ifdef CAPITALIZE
- if (good (upcase (newword)))
- {
- if (ins_cap (newword, word) < 0)
- return;
- }
- #else
- if (good (newword))
- {
- if (ins_cap (newword, word) < 0)
- return;
- }
- #endif
- }
- }
- }
-
- void transposedletter (char *word)
- {
- char newword[BUFSIZ];
- register int t;
- register char *p;
-
- strcpy (newword, word);
- for (p = newword; p[1]; p++)
- {
- t = p[0];
- p[0] = p[1];
- p[1] = t;
- #ifdef CAPITALIZE
- if (good (upcase (newword)))
- {
- if (ins_cap (newword, word) < 0)
- return;
- }
- #else
- if (good (newword))
- {
- if (ins_cap (newword, word) < 0)
- return;
- }
- #endif
- t = p[0];
- p[0] = p[1];
- p[1] = t;
- }
- }
-
- /* Insert one or more correctly capitalized versions of pattern */
- int ins_cap (char *word, char *pattern)
- {
- static char newword[BUFSIZ];
- register char *p;
- char *psave;
- register int wcount;
-
- if (*word == 0)
- return 0;
-
- strcpy (newword, word);
- #ifdef CAPITALIZE
- if (lastdent->allcaps)
- return insert (upcase (newword)); /* Uppercase required */
- for (p = pattern; *p; p++)
- if (mylower (*p))
- break;
- if (*p == '\0')
- return insert (upcase (newword)); /* Pattern was all caps */
- for (p = pattern; *p; p++)
- if (myupper (*p))
- break;
- if (*p == '\0')
- { /* Pattern was all lower */
- if (!lastdent->followcase && !lastdent->capitalize)
- return insert (lowcase (newword));
- /*
- ** If there's a followcase version that's all-lower,
- ** insert only that version.
- */
- if (lastdent->followcase)
- {
- p = lastdent->word;
- p += strlen (p) + 1;
- wcount = (*p++ & 0xFF);
- while (--wcount >= 0)
- {
- for (psave = ++p;
- *p && !myupper (*p);
- p++)
- ;
- if (*p == '\0') /* Was it all lowercase? */
- return insert (psave); /* Yup, quit */
- while (*p++)
- ; /* Skip to next case sample */
- }
- }
- }
- /*
- ** The sample wasn't all-upper, and either it wasn't all-lower or
- ** all-lower is illegal. Insert all legal capitalizations. In
- ** some cases, this may include all-lowercase.
- */
- if (lastdent->capitalize)
- {
- lowcase (newword);
- if (mylower (newword[0]))
- newword[0] = toupper (newword[0]);
- insert (newword);
- }
- if (lastdent->followcase)
- {
- p = lastdent->word;
- p += strlen (p) + 1;
- wcount = (*p++ & 0xFF);
- while (--wcount >= 0)
- {
- /* Insert every variation; it's easier */
- if (insert (++p) < 0)
- return -1;
- while (*p++)
- ; /* Skip to end of sample */
- }
- return 0;
- }
- if (lastdent->capitalize)
- return 0;
- /*
- ** We get here only if none of the special capitalization flags are
- ** set. If first letter of the pattern is capitalized, capitalize
- ** the first letter of the result. Otherwise produce all lowercase.
- */
- lowcase (newword);
- if (myupper (pattern[0]) && mylower (newword[0]))
- newword[0] = toupper (newword[0]);
- return insert (newword);
- #else
- if (myupper (pattern[0]))
- {
- if (myupper (pattern[1]))
- {
- for (p = word, q = newword; *p; p++, q++)
- {
- if (mylower (*p))
- *q = toupper (*p);
- else
- *q = *p;
- }
- *q = 0;
- }
- else
- {
- if (mylower (word[0]))
- newword[0] = toupper (word[0]);
- else
- newword[0] = word[0];
-
- for (p = word + 1, q = newword + 1; *p; p++, q++)
- if (myupper (*p))
- *q = tolower (*p);
- else
- *q = *p;
-
- *q = 0;
- }
- }
- else
- {
- for (p = word, q = newword; *p; p++, q++)
- if (myupper (*p))
- *q = tolower (*p);
- else
- *q = *p;
- *q = 0;
- }
- return insert (newword);
- #endif
- }
-
- char *getline (char *s)
- {
- register char *p;
- register int c;
-
- p = s;
-
- while (1)
- {
- c = (getccon () & NOPARITY);
- if (c == '\\')
- {
- putccon ('\\');
- c = (getccon () & NOPARITY);
- backup ();
- putccon (c);
- *p++ = c;
- }
- else if (c == ('G' & 037))
- {
- return (NULL);
- }
- else if ((c == '\n') || (c == '\r'))
- {
- *p = 0;
- return (s);
- }
- else if (c == '\b')
- {
- if (p != s)
- {
- p--;
- backup ();
- putccon (' ');
- backup ();
- }
- }
- else
- {
- *p++ = c;
- putccon (c);
- }
- }
- }
-
- void servermode (void)
- {
- long rexxbit;
- long returnbits;
- rexxbit = upRexxPort ("IRexxSpell", rcl, NULL, &disp);
-
- setbuf (stdin, NULL);
- setbuf (stdout, NULL);
-
- while (KeepGoing)
- {
- returnbits = Wait (rexxbit | SIGBREAKF_CTRL_C);
- if (returnbits & SIGBREAKF_CTRL_C)
- KeepGoing = 0;
- if (returnbits & rexxbit)
- dispRexxPort ();
- }
- /*
- * With Rexx, we need to bring the port down. You might make this
- * part of exit() for programs that have multiple paths to exit.
- */
- dnRexxPort ();
- }
-
-
- /*
- * Now we get into the actual code necessary for our REXX port; functions
- * that do the real work. Note that this program was not structured
- * particularly nicely for Rexx; I had to write each of these functions.
- * Many programs have these subroutines already in place; they are called
- * as part of the event loop. This progam, however, just has one big
- * switch statement with different actions . . .
- *
- * First, our locals.
- */
- /*
- * This is our main dispatch function.
- */
- void disp (struct RexxMsg *msg, struct rexxCommandList *dat, char *p)
- {
- (*(dat->userdata)) (msg, p);
- }
-
- /*
- * This handler adds a word to the `global personal dictionary.'
- *
- * Now, in English, the word is added to whatever personal
- * dictionary was found when ISpell was started up in ARexx
- * server mode. (Under a multiuser system, we might want to
- * restrict who can add words to this dictionary. For now
- * we just do it! Yes, the AmigaOS is multiuser, hehe :-).
- * No protection, the way true hackers like it, you (the
- * user) get more rope to hang yourself :-), err the system
- * with :-).
- */
- void rexxadd (struct RexxMsg *msg, char *p)
- {
- if (*p)
- treeinsert (p, 1);
- treeoutput ();
- replyRexxCmd (msg, 0L, 0L, "ok");
- }
-
- /*
- * The quick version does not write the changes to disk.
- * Useful if you will be adding many words. Be sure to
- * call rexxadd at the end of the list (pass a null word,
- * or a valid new word to be added).
- */
- void rexxquickadd (struct RexxMsg *msg, char *p)
- {
- if (*p)
- treeinsert (p, 1);
- replyRexxCmd (msg, 0L, 0L, "ok");
- }
-
- /*
- * This handler checks the spelling of a word.
- */
- void rexxcheck (struct RexxMsg *msg, char *p)
- {
- char buf[512];
- register int i;
-
- if (good (p))
- {
- if (rootword[0] == 0)
- strcpy (buf, "*");
- else
- sprintf (buf, "+ %s", rootword);
- }
- else
- {
- makepossibilities (p);
- if (possibilities[0][0])
- {
- int bufend = 1;
- int possibilitysize;
-
- strcpy (buf, "&");
- for (i = 0; i < MAXPOSSIBLE; i++)
- {
- if (possibilities[i][0] == 0)
- break;
- possibilitysize = strlen(possibilities[i]);
- if ((possibilitysize + bufend) > 511)
- break;
- strcpy (&(buf[bufend++]), " ");
- strcpy (&(buf[bufend]), possibilities[i]);
- bufend += possibilitysize;
- }
- }
- else
- strcpy (buf, "#");
- }
- replyRexxCmd (msg, 0L, 0L, buf);
- }
-
- /*
- * This handler checks the spelling of a word, it does
- * not try to find replacement words as above. It only
- * determines whether or not the word is in the dictoinary.
- */
- void rexxquickcheck (struct RexxMsg *msg, char *p)
- {
- if (good (p))
- replyRexxCmd (msg, 0L, 0L, "ok");
- else
- replyRexxCmd (msg, 0L, 0L, "bad");
- }
-
- void rexxlookup (struct RexxMsg *msg, char *p)
- {
- char buf[512];
- char cmd[512];
- char *rval;
- int whence = 0;
- int bufend = 1;
- int lookupsize;
-
- strcpy (buf, "&");
- sprintf (cmd, "^%s$", p);
- while ((rval = do_regex_lookup (cmd, whence++)) != NULL)
- {
- lookupsize = strlen(rval);
- if ((lookupsize + bufend) > 511)
- break;
- strcpy (&(buf[bufend++]), " ");
- strcpy (&(buf[bufend]), rval);
- bufend += lookupsize;
- }
- replyRexxCmd (msg, 0L, 0L, buf);
- }
-
- /*
- * This handler checks the spelling of a file.
- */
- void rexxfilecheck (struct RexxMsg *msg, char *p)
- {
- char *cp;
-
- currentfile = p;
-
- if ((infile = fopen (p, "r")) == NULL)
- {
- replyRexxCmd (msg, 0L, 0L, "Error: Can't open input file");
- return;
- }
-
- tmpnam (tempfile);
-
- if ((outfile = fopen (tempfile, "w")) == NULL)
- {
- replyRexxCmd (msg, 0L, 0L, "Error: Can't open output file");
- return;
- }
-
- quit = 0;
-
- /* See if the file is a .tex file. If so, set the appropriate flag. */
- if ((cp = strrchr (p, '.')) != NULL && strcmp (cp, ".tex") == 0)
- tflag = 1;
- else
- tflag = 0;
-
- lflag = 1;
-
- checkfile ();
-
- fclose (infile);
- fclose (outfile);
-
- replyRexxCmd (msg, 0L, 0L, tempfile);
- }
-
- /*
- * This handler checks the spelling of a file using extended method.
- */
- void rexxextendedfilecheck (struct RexxMsg *msg, char *p)
- {
- char *cp;
-
- wflag = 1;
- RexxMsg = msg;
-
- currentfile = p;
-
- if ((infile = fopen (p, "r")) == NULL)
- {
- replyRexxCmd (msg, 0L, 0L, "Error: Can't open input file");
- return;
- }
-
- quit = 0;
-
- /* See if the file is a .tex file. If so, set the appropriate flag. */
- if ((cp = strrchr (p, '.')) != NULL && strcmp (cp, ".tex") == 0)
- tflag = 1;
- else
- tflag = 0;
-
- lflag = 1;
-
- checkfile ();
-
- fclose (infile);
-
- replyRexxCmd (msg, 0L, 0L, "ok");
-
- wflag = 0;
- }
-
- /*
- * This handler returns the version of the program.
- */
- void rexxversion (struct RexxMsg *msg, char *p)
- {
- char buf[512];
- int bufend = strlen(Version_ID);
- int namesize;
- int i;
-
- strcpy(buf, Version_ID);
- buf[bufend++] = '\n';
- for (i = 0; rcl[i].name != NULL; i++)
- {
- namesize = strlen(rcl[i].name);
- if ((namesize + bufend) > 511)
- break;
- strcpy (&(buf[bufend++]), " ");
- strcpy (&(buf[bufend]), rcl[i].name);
- bufend += namesize;
- }
- replyRexxCmd (msg, 0L, 0L, buf);
- }
-
- /*
- * This handler sets the exit flag.
- */
- void rexxexit (struct RexxMsg *msg, char *p)
- {
- KeepGoing = 0;
- replyRexxCmd (msg, 0L, 0L, "bye");
- }
-
- void askmode (void)
- {
- char buf[BUFSIZ];
- register int i;
-
- if (fflag)
- {
- if (freopen (askfilename, "w", stdout) == NULL)
- {
- fprintf (stderr, "Can't create %s\n", askfilename);
- exit (1);
- }
- }
-
- setbuf (stdin, NULL);
- setbuf (stdout, NULL);
-
- while (xgets (buf) != NULL)
- {
- /* *line is like `i', @line is like `a' */
- if (buf[0] == '*' || buf[0] == '@')
- {
- treeinsert (buf + 1, buf[0] == '*');
- fprintf (stdout, "*\n");
- treeoutput ();
- }
- else if (good (buf))
- {
- if (rootword[0] == 0)
- {
- fprintf (stdout, "*\n"); /* perfect match */
- }
- else
- {
- fprintf (stdout, "+ %s\n", rootword);
- }
- }
- else
- {
- makepossibilities (buf);
- if (possibilities[0][0])
- {
- fprintf (stdout, "& ");
- for (i = 0; i < MAXPOSSIBLE; i++)
- {
- if (possibilities[i][0] == 0)
- break;
- fprintf (stdout, "%s ", possibilities[i]);
- }
- fprintf (stdout, "\n");
- }
- else
- {
- fprintf (stdout, "#\n");
- }
- }
- if (sflag)
- {
- stop ();
- if (fflag)
- {
- rewind (stdout);
- creat (askfilename, 0666);
- }
- }
- }
- }
-
- /* Copy/ignore "cnt" number of characters pointed to by *cc. */
- void copyout (char **cc, int cnt)
- {
- while (--cnt >= 0)
- {
- if (*(*cc) == 0)
- break;
- if (!lflag)
- putc (*(*cc), outfile);
- (*cc)++;
- }
- }
-
- void lookharder (char *string)
- {
- char cmd[150], grepstr[100];
- register char *g, *s;
-
- g = grepstr;
- for (s = string; *s != '\0'; s++)
- if (*s == '*')
- {
- *g++ = '.';
- *g++ = '*';
- }
- else
- *g++ = *s;
- *g = '\0';
- if (grepstr[0])
- regex_dict_lookup (cmd, grepstr);
- }
-
- void regex_dict_lookup (char *cmd, char *grepstr)
- {
- char *do_regex_lookup ();
- char *rval;
- int whence = 0;
- int quit = 0;
- int count = 0;
- sprintf (cmd, "^%s$", grepstr);
- while (!quit && (rval = do_regex_lookup (cmd, whence++)) != NULL)
- {
- int ch;
- printcon ("%s\n", rval);;
- if ((count++ % (li - 1)) == 0)
- {
- inverse ();
- printcon ("-- more --");
- normal ();
- if ((ch = getccon ()) == 'q' || ch == 'Q' || ch == 'x' || ch == 'X')
- quit = 1;
- printcon ("\r \r");
- }
- }
- if (rval == NULL)
- {
- inverse ();
- printcon ("--eow--");
- normal ();
- getccon ();
- }
- }
-